package com.liming.chat.socket;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import jakarta.websocket.OnClose;
import jakarta.websocket.OnMessage;
import jakarta.websocket.OnOpen;
import jakarta.websocket.Session;
import jakarta.websocket.server.PathParam;
import jakarta.websocket.server.ServerEndpoint;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author liming
 * @date 2025/5/28
 */
@Slf4j
@Component
@ServerEndpoint("/websocket/chat/{userId}/{room}")
public class WebSocketServer {

    private static final List<String> ROOM_LIST = List.of("低分局", "高分局");

    /**
     * Map<房间名称, Map<用户ID, 该用户websocket连接>>
     */
    private static final Map<String, Map<String, WebSocketServer>> ROOM_USER_SOCKET_MAP = new ConcurrentHashMap<>();

    /**
     * Session
     */
    private Session session;

    @OnOpen
    public void onOpen(Session session, @PathParam("userId") String userId, @PathParam("room") String room) {
        log.info("WebSocketServer onOpen");
        if (!ROOM_LIST.contains(room)) {
            throw new RuntimeException("房间不存在");
        }
        this.session = session;
        ROOM_USER_SOCKET_MAP.computeIfPresent(room, (key, value) -> {
            value.put(userId, this);
            return value;
        });
        ConcurrentHashMap<String, WebSocketServer> userSocketMap = new ConcurrentHashMap<>();
        userSocketMap.put(userId, this);
        ROOM_USER_SOCKET_MAP.putIfAbsent(room, userSocketMap);
    }

    @OnMessage
    public void onMessage(String jsonStr) throws IOException {
        JSONObject obj = JSONUtil.parseObj(jsonStr);
        log.info("消息：{}", obj);
        // 连接路径参数
        Map<String, String> pathParameters = session.getPathParameters();
        String messageUserId = pathParameters.get("userId");
        String room = pathParameters.get("room");
        for (Map.Entry<String, WebSocketServer> entry : ROOM_USER_SOCKET_MAP.get(room).entrySet()) {
            String userIdInRoom = entry.getKey();
            entry.getValue().sendMessage(jsonStr);
        }
    }

    @OnClose
    public void onClose() {
        log.info("WebSocketServer onClose");
        Map<String, String> pathParameters = session.getPathParameters();
        String room = pathParameters.get("room");
        // 用户退出房间时，如果存在该房间，则在房间内删除该用户
        if (ROOM_USER_SOCKET_MAP.containsKey(room)) {
            Map<String, WebSocketServer> map = ROOM_USER_SOCKET_MAP.get(room);
            map.remove(pathParameters.get("userId"));
        }
    }

    /**
     * 实现服务器主动推送
     */
    public void sendMessage(String jsonStr) {
        this.session.getAsyncRemote().sendText(jsonStr);
    }
}
